#include "Router.h"


std::map<std::string, Router *> Router::interface_map;

Router::Router()
{
	ngbr_router_iterator = ngbr_router.begin();
}

void Router::add_interface ( const std::string& addr_ip )
{
	if (IPList::isIP(addr_ip))
	{
		interface_map[addr_ip] = this;
		interfaces.push_back(addr_ip);
	}
}

void Router::add_ngbr_interface ( const std::string& addr_ip )
{
	ngbr_interfaces.push_back(addr_ip);
}

void Router::complete_router_neighbourhood()
{
	std::map<std::string, Router *>::iterator it_tmp;

	IPList::iterator it;

	for ( it = ngbr_interfaces.begin() ; it != ngbr_interfaces.end() ; ++it )
		{
			// Check if the router of this interface was found 
			it_tmp = Router::interface_map.find(*it);
			if ( it_tmp != Router::interface_map.end() )
				ngbr_router.insert(it_tmp->second);
		}
}

std::ostream& operator <<(std::ostream& stream, const Router& router)
{
	stream << "Router : " << "Router" << &router << std::endl;

	stream << "Interfaces du routeur : " << std::endl;
	stream << router.interfaces << std::endl; 
  //  stream << "Interfaces voisines : " << std::endl;
	//stream << router.ngbr_interfaces << std::endl;

	stream << "Routeur voisin ( " << router.ngbr_router.size() << " : " << std::endl;
	for ( std::set<Router *>::iterator it = router.ngbr_router.begin() ; 
		it != router.ngbr_router.end() ; ++it )
			stream << "Router" << *it << std::endl; 

	stream << "--------------------" << std::endl;
    return stream; 
}

std::list<Router::RouterPath> Router::get_all_paths (Router * destination)
{
	
	std::list<Router::RouterPath> result;

	RouterPath current_path;
	Router * tmp;


	current_path.push_back(this);

	std::cout << "size : " << current_path.size() << std::endl;

	while ( !current_path.empty() )
	{
		//std::cout << current_path.print_path() << std::endl;
			
		if ( current_path.back()->ngbr_router_iterator == current_path.back()->ngbr_router.end() )
		{
			current_path.pop_back();
		}
		else
		{	
			tmp = current_path.back();
			current_path.push_back(*(current_path.back()->ngbr_router_iterator));
			tmp->ngbr_router_iterator++;

			if ( current_path.back() == destination )
			{
				std::cout << current_path.print_path() << std::endl;
				result.push_back(current_path);
				current_path.pop_back();
			}

		}
	}

	return result;
}

std::string Router::RouterPath::print_path()
{
	std::string res;
	std::list<Router *>::const_iterator it;

	char addr[10];


	for ( it = begin() ; it != end() ; ++it )
	{
			sprintf(addr, "%p", *it);
			res = res+addr+", ";
	}

	res = res+"\n";

	return res;
}

void Router::RouterPath::push_back (Router * r)
{
	if ( path_set.insert(r).second ) /* r is new */
	{
		std::list<Router *>::push_back(r);
		r->ngbr_router_iterator = r->ngbr_router.begin();
	}
}
				
void Router::RouterPath::pop_back()
{
	Router * tmp = back();
	path_set.erase(tmp);
	std::list<Router *>::pop_back();
}
	

